home *** CD-ROM | disk | FTP | other *** search
- /*
- * morph.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* MORPH: performs erosion, dilation, opening, closing with
- * square structuring element of size kxk
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <tiffimage.h> /* picfile info on images */
- #include <images.h>
- extern void print_sos_lic ();
-
- #define ON 255 /* binarization values */
- #define OFF 0
- #define NITER_DFLT 1 /* default threshold on number iteratoins */
- #define SIZE_DFLT 3 /* default size of structuring element */
-
- int input (int, char **, long *, long *, long *, long *);
- int usage (short);
-
- int argc;
- char *argv[];
- long *nIter; /* number of iterations to perform */
- long *opType; /* operation type */
- long *size;
-
-
- main (argc, argv)
- int argc;
- char *argv[];
-
- {
- Image *imgI, *imgO; /* input and output image structures */
- unsigned char **imgIn, **imgOut; /* input and output image arrays */
- long width, height; /* size of image */
- long nIter; /* number of iterations to perform */
- long opType; /* operation type */
- long size; /* structuring element size (must be odd) */
- long invertFlag; /* invert input image before processing */
- long sizeD2; /* half structuring element size */
- long xEnd, yEnd; /* end of image within 1-pixel borders */
- long sum; /* sum of ON pixels in neighborhood */
- long sumAll; /* sum of (size x size) */
- long nChange; /* number pixels changed on iteration */
- long x, y, i, j, n;
-
- /* user input */
- if ((input (argc, argv, &nIter, &opType, &size, &invertFlag)) < 0)
- return (-1);
- sizeD2 = size / 2;
-
- /* open input and output image */
- imgI = ImageIn (argv[1]);
- imgIn = ImageGetPtr (imgI);
- height = ImageGetHeight (imgI);
- width = ImageGetWidth (imgI);
- printf ("Input mage size is %dx%d.\n", width, height);
-
- imgO = ImageAlloc (height, width, 8);
- imgOut = ImageGetPtr (imgO);
-
- /* invert image */
- if (invertFlag) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgIn[y][x] = 255 - imgIn[y][x];
- }
-
- /* zero image borders */
- yEnd = height - sizeD2;
- xEnd = width - sizeD2;
- for (y = 0; y < height; y++) {
- for (x = 0; x <= sizeD2; x++)
- imgIn[y][x] = OFF;
- for (x = xEnd - 1; x < width; x++)
- imgIn[y][x] = OFF;
- }
- for (x = 0; x < width; x++) {
- for (y = 0; y <= sizeD2; y++)
- imgIn[y][x] = OFF;
- for (y = yEnd - 1; y < height; y++)
- imgIn[y][x] = OFF;
- }
-
- /* write input to output image */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgOut[y][x] = imgIn[y][x];
-
- /* perform morphological iterations */
- sumAll = size * size;
- for (n = 0; n < nIter; n++) {
- nChange = 0;
- for (y = sizeD2; y < yEnd; y++) {
- for (x = sizeD2; x < xEnd; x++) {
- sum = 0;
- for (i = -sizeD2; i <= sizeD2; i++)
- for (j = -sizeD2; j <= sizeD2; j++)
- sum += (imgIn[y + i][x + j] > 0) ? 1 : 0;
-
- switch (opType) {
- case 1: /* dilation */
- if (sum > 0) {
- imgOut[y][x] = ON;
- nChange++;
- }
- break;
- case 2: /* erosion */
- if (sum < sumAll) {
- imgOut[y][x] = OFF;
- nChange++;
- }
- break;
- case 3: /* dilation-erosion */
- if (sum > 0) {
- imgOut[y][x] = ON;
- nChange++;
- }
- break;
- case 4: /* erosion-dilation */
- if (sum < sumAll) {
- imgOut[y][x] = OFF;
- nChange++;
- }
- break;
- default:
- usage (1);
- }
- }
- }
- printf ("iteration %d: nChange = %d\n", n, nChange);
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgIn[y][x] = imgOut[y][x];
- if (opType == 4)
- opType = 3;
- else if (opType == 3)
- opType = 4;
- }
-
- /* un-invert image */
- if (invertFlag) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgOut[y][x] = 255 - imgOut[y][x];
- }
-
- ImageOut (argv[2], imgO);
-
- return (0);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- int
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: morph inimg outimg [-i ITERATIONS] [-o OPERATION]\n");
- printf (" [-s SIZE] [-I] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nmorph performs morphological processing on binary image\n\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: input image filename (TIF)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -i ITERATIONS: number of iterations to perform.\n");
- printf (" (default = %d)\n", NITER_DFLT);
- printf (" -o OPERATION: for dilation(1), erosion(2), closing(3),\n");
- printf (" or opening(4) (default = 1).\n");
- printf (" closing operation is alternating dilation-erosion;\n");
- printf (" opening operation is alternating erosion-dilation;\n");
- printf (" for opening or closing, the number of iterations is\n");
- printf (" the sum of the comprising dilation and erosion iterations.\n");
- printf (" -s SIZE: size of structuring element -- must be odd and >=3\n");
- printf (" (default = %d)\n", SIZE_DFLT);
- printf (" -I: invert input image before processing\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &nIter, &opType, &size);
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- int
- input (argc, argv, nIter, opType, size, invertFlag)
- int argc;
- char *argv[];
- long *nIter; /* number of iterations to perform */
- long *opType; /* operation type */
- long *size; /* size of structuring element */
- long *invertFlag; /* size of structuring element */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *nIter = NITER_DFLT;
- *opType = 1;
- *size = SIZE_DFLT;
- *invertFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-i") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *nIter = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-o") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *opType = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-s") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *size = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-I") == 0)
- *invertFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- if (*size < 3)
- *size = 3;
- if ((*size % 2) == 0) {
- *size -= 1;
- printf ("Structuring element size must be odd, set to %d\n", *size);
- }
-
- return (0);
- }
-